#pragma once

#include "new_api_comm.h"

typedef enum
{
    GPIOA = 0x400010A0,
    GPIOB = 0x400010C0,
} gpio_port_t;

typedef enum
{
    GPIO_P00 = 0x0001,
    GPIO_P01 = 0x0002,
    GPIO_P02 = 0x0004,
    GPIO_P03 = 0x0008,
    GPIO_P04 = 0x0010,
    GPIO_P05 = 0x0020,
    GPIO_P06 = 0x0040,
    GPIO_P07 = 0x0080,
    GPIO_P08 = 0x0100,
    GPIO_P09 = 0x0200,
    GPIO_P10 = 0x0400,
    GPIO_P11 = 0x0800,
    GPIO_P12 = 0x1000,
    GPIO_P13 = 0x2000,
    GPIO_P14 = 0x4000,
    GPIO_P15 = 0x8000,
    GPIO_P16 = 0x10000,
    GPIO_P17 = 0x20000,
    GPIO_P18 = 0x40000,
    GPIO_P19 = 0x80000,
    GPIO_P20 = 0x100000,
    GPIO_P21 = 0x200000,
    GPIO_P22 = 0x400000,
    GPIO_P23 = 0x800000,
    GPIO_ALL = 0xFFFFFFFF
} gpio_pin_t; // GPIO引脚

typedef enum
{
    GPIO_PA00 = 0,
    GPIO_PA01,
    GPIO_PA02,
    GPIO_PA03,
    GPIO_PA04,
    GPIO_PA05,
    GPIO_PA06,
    GPIO_PA07,
    GPIO_PA08,
    GPIO_PA09,
    GPIO_PA10,
    GPIO_PA11,
    GPIO_PA12,
    GPIO_PA13,
    GPIO_PA14,
    GPIO_PA15,
    GPIO_PA16,
    GPIO_PA17,
    GPIO_PA18,
    GPIO_PA19,
    GPIO_PA20,
    GPIO_PA21,
    GPIO_PA22,
    GPIO_PA23,
    GPIO_PB00,
    GPIO_PB01,
    GPIO_PB02,
    GPIO_PB03,
    GPIO_PB04,
    GPIO_PB05,
    GPIO_PB06,
    GPIO_PB07,
    GPIO_PB08,
    GPIO_PB09,
    GPIO_PB10,
    GPIO_PB11,
    GPIO_PB12,
    GPIO_PB13,
    GPIO_PB14,
    GPIO_PB15,
    GPIO_PB16,
    GPIO_PB17,
    GPIO_PB18,
    GPIO_PB19,
    GPIO_PB20,
    GPIO_PB21,
    GPIO_PB22,
    GPIO_PB23,
    GPIO_NONE,
} gpio_t;

typedef enum
{
    LOW,
    HIGH,
} gpio_level_t;

typedef enum
{
    GPIO_MODE_IN_FLOAT,          // 浮空输入
    GPIO_MODE_IN_PULLUP,         // 上拉输入
    GPIO_MODE_IN_PULLDOWN,       // 下拉输入
    GPIO_MODE_OUT_PUSHPULL_5mA,  // 推挽输出最大5mA
    GPIO_MODE_OUT_PUSHPULL_20mA, // 推挽输出最大20mA
} gpio_mode_t;                   // GPIO模式

typedef enum
{
    IT_LOW_LEVEL,  // 低电平触发
    IT_HIGH_LEVEL, // 高电平触发
    IT_FALL_EDGE,  // 下降沿触发
    IT_RISE_EDGE,  // 上升沿触发
} gpio_it_type_t;

// GPIO中断回调函数原型
typedef void (*gpio_it_cb_t)(gpio_t port);

// GPIO
// port&pin
/**
 * @brief 输出指定PORT的指定PIN(s)低电平
 *
 * @param port GPIOA/GPIOB
 * @param pin GPIO_P00/.../ GPIO_P23/GPIO_ALL
 */
#define gpio_set_port_low(port, pin) (*((PUINT32V)(port + 12)) |= pin)

/**
 * @brief 输出指定PORT的指定PIN(s)高电平
 *
 * @param port GPIOA/GPIOB
 * @param pin GPIO_P00/.../ GPIO_P23/GPIO_ALL
 */
#define gpio_set_port_high(port, pin) (*((PUINT32V)(port + 8)) |= pin)

/**
 * @brief 输出指定PORT的指定PIN(s)电平
 *
 * @param port GPIOA/GPIOB
 * @param pin GPIO_P00/.../ GPIO_P23/GPIO_ALL
 * @param level LOW/HIGH
 */
#define gpio_set_port_level(port, pin, level) \
    ((level) ? gpio_set_port_high(port, pin) : gpio_set_port_low(port, pin))

/**
 * @brief 获取指定PORT的指定PIN(s)电平
 *
 * @param port GPIOA/GPIOB
 * @param pin GPIO_P00/.../ GPIO_P23/GPIO_ALL
 * @return gpio_level_t LOW/HIGH
 */
#define gpio_get_port_level(port, pin) ((*((PUINT32V)(port + 4)) & (pin)) ? HIGH : LOW)

/**
 * @brief 获取指定PIN的数字号,如有多个PIN,返回最高PIN数字
 *
 * @param pin  GPIO_P00/.../ GPIO_P23
 * @return uint8_t 0...23
 */
uint8_t gpio_get_pin_number(gpio_pin_t pin);

/**
 * @brief 设置指定PORT的指定PIN(s)模式
 *
 * @param port GPIOA/GPIOB
 * @param pin GPIO_P00/.../ GPIO_P23/GPIO_ALL
 * @param mode GPIO_MODE_IN_FLOAT/...IN_PULLUP/...IN_PULLDOWN/...OUT_PUSHPULL_5mA/...OUT_PUSHPULL_20mA
 */
void gpio_mode_port_pin(gpio_port_t port, gpio_pin_t pin, gpio_mode_t mode);

/**
 * @brief 设置指定PORT的指定PIN(s)中断模式
 *
 * @param port GPIOA/GPIOB
 * @param pin GPIO_P00/.../ GPIO_P23/GPIO_ALL
 * @param type IT_LOW_LEVEL/...HIGH_LEVEL/...FALL_EDGE/...RISE_EDGE
 */
void gpio_it_mode_port_pin(gpio_port_t port, gpio_pin_t pin, gpio_it_type_t type);

/**
 * @brief 使能/禁用指定PORT的指定PIN(s)中断
 *
 * @param port  GPIOA/GPIOB
 * @param pin   GPIO_P00/.../ GPIO_P23/GPIO_ALL
 * @param en    ENABLE/DISABLE
 */
void gpio_it_enable_port_pin(gpio_port_t port, gpio_pin_t pin, en_state_t en);

// fpin
/**
 * @brief 设置指定GPIO模式
 *
 * @param pin GPIO_PA00/.../ GPIO_PA23/ GPIO_PB00/.../ GPIO_PB23
 * @param mode GPIO_MODE_IN_FLOAT/...IN_PULLUP/...IN_PULLDOWN/...OUT_PUSHPULL_5mA/...OUT_PUSHPULL_20mA
 */
void gpio_set_mode(gpio_t pin, gpio_mode_t mode);

/**
 * @brief 设置指定GPIO电平
 *
 * @param pin GPIO_PA00/.../ GPIO_PA23/ GPIO_PB00/.../ GPIO_PB23
 * @param level LOW/HIGH
 */
void gpio_set_level(gpio_t pin, gpio_level_t level);

/**
 * @brief 获取指定GPIO电平
 *
 * @param pin GPIO_PA00/.../ GPIO_PA23/ GPIO_PB00/.../ GPIO_PB23
 * @return gpio_level_t LOW/HIGH
 */
gpio_level_t gpio_get_level(gpio_t pin);

/**
 * @brief 注册GPIO中断回调函数
 *
 * @param cb
 */
void gpio_register_it_cb(gpio_it_cb_t cb);

/**
 * @brief 设置指定GPIO中断模式，默认开启中断
 *
 * @param pin GPIO_PA00/.../ GPIO_PA23/ GPIO_PB00/.../ GPIO_PB23
 * @param type IT_LOW_LEVEL/...HIGH_LEVEL/...FALL_EDGE/...RISE_EDGE
 */
void gpio_it_mode(gpio_t pin, gpio_it_type_t type);

/**
 * @brief 使能/禁用指定GPIO中断
 *
 * @param pin GPIO_PA00/.../ GPIO_PA23/ GPIO_PB00/.../ GPIO_PB23
 * @param en ENABLE/DISABLE
 */
void gpio_it_enable(gpio_t pin, en_state_t en);
